﻿using System;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Xml;

using umbraco;
using umbraco.cms.businesslogic.web;
using umbraco.cms.helpers;
using umbraco.presentation.nodeFactory;

namespace Our.Umbraco.DataType.Bitly
{
	/// <summary>
	/// The bit.ly API allows developers to interact in a programmatic way with the bit.ly website.
	/// </summary>
	/// <remarks>The current API version is 2.0.1.</remarks>
	public class Helper
	{
		/// <summary>
		/// Calls the bit.ly API to shorten a long URL.
		/// </summary>
		/// <param name="username">A bit.ly username.</param>
		/// <param name="apiKey">A bit.ly API key.</param>
		/// <param name="longUrl">The long URL.</param>
		/// <returns>
		/// Returns the shortered bit.ly URL.
		/// </returns>
		public static String GetBitlyUrl(String username, String apiKey, String longUrl)
		{
			// build the Bit.ly API URL
			string url = String.Format("http://api.bit.ly/v3/shorten?login={0}&apiKey={1}&longUrl={2}&format=txt", username, apiKey, longUrl);

			string data = String.Empty;

			// using a WebClient for easy access.
			using (var webClient = new WebClient())
			{
				data = webClient.DownloadString(url);
			}

			//// File.WriteAllText(System.Web.HttpContext.Current.Server.MapPath("~/bitly_debug.txt"), data);

			// if the response starts with 'http;//' then we assume its a valid bit.ly URL.
			return data.StartsWith("http://") ? data : string.Empty;
		}

		/// <summary>
		/// Guesses the nice URL.
		/// </summary>
		/// <param name="nodeId">The node id.</param>
		/// <returns></returns>
		public static string GuessNiceUrl(int nodeId)
		{
			const string HASH = "#";
			const string HTTP = "http://";
			Node node = new Node(nodeId);
			string niceUrl = node.NiceUrl;
			bool published = node.Path != null;

			if (!niceUrl.StartsWith(HTTP) || !published)
			{
				const string URLNAME = "umbracoUrlName";
				bool hasDomain = false;
				string domain = HttpContext.Current.Request.ServerVariables["SERVER_NAME"].ToLower();
				string nodeName;
				string nodePath;
				int nodeParentId;

				// if the node is published, get from the nodeFactory
				if (published)
				{
					nodeName = node.GetProperty(URLNAME) != null && !string.IsNullOrEmpty(node.GetProperty(URLNAME).Value) ? node.GetProperty(URLNAME).Value : node.Name;
					nodePath = node.Path;
					nodeParentId = node.Parent != null ? node.Parent.Id : -1;
				}
				else
				{
					// otherwise, get from the Document object.
					Document doc = new Document(nodeId);
					nodeName = doc.getProperty(URLNAME) != null && doc.getProperty(URLNAME).Value != null && !string.IsNullOrEmpty(doc.getProperty(URLNAME).Value.ToString()) ? doc.getProperty(URLNAME).Value.ToString() : doc.Text;
					nodePath = doc.Path;
					nodeParentId = doc.ParentId;
				}

				// check if the node has a domain associated.
				if (UmbracoSettings.UseDomainPrefixes)
				{
					// get the path
					string[] path = nodePath.Split(',');

					// loop through each part of the path in reverse order
					for (int i = path.Length - 1; i >= 0; i--)
					{
						int partId;
						if (int.TryParse(path[i], out partId))
						{
							Domain[] domains = Domain.GetDomainsById(partId);
							if (domains != null && domains.Length > 0)
							{
								hasDomain = true;
								domain = domains[0].Name;
								break;
							}
						}
					}
				}

				// if the node is unpublished...
				if (!published)
				{
					// get the published node for the parent node.
					var parentNode = new Node(nodeParentId);
					if (parentNode.Path != null || (nodeParentId == -1 && !hasDomain))
					{
						const string DOTASPX = ".aspx";
						int level = parentNode.Path.Split(',').Length;
						string parentUrl = nodeParentId > 0 && !(level == 2 && GlobalSettings.HideTopLevelNodeFromPath) ? parentNode.NiceUrl : string.Empty;
						string urlName = string.Concat('/', url.FormatUrl(nodeName.ToLower()));
						string fileExtension = GlobalSettings.UseDirectoryUrls ? string.Empty : DOTASPX;

						// construct the NiceUrl for the unpublished node.
						niceUrl = string.Concat(parentUrl.Replace(DOTASPX, string.Empty), urlName, fileExtension);
					}
				}

				// if the node has a domain, and is unpublished, use the domain.
				if (niceUrl == HASH && hasDomain)
				{
					niceUrl = string.Concat(HTTP, domain);
				}

				// if the NiceUrl doesn't start with 'http://' (and isn't '#') then prepend it.
				if (!niceUrl.StartsWith(HTTP) && niceUrl != HASH)
				{
					niceUrl = string.Concat(HTTP, domain, niceUrl);
				}
			}

			// return the NiceUrl
			return niceUrl;
		}
	}
}

